package com.optitronics.beans;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.TypedQuery;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.transaction.annotation.Transactional;

import com.optitronics.ui.OrderItemDisplayForm;
import com.optitronics.util.OptitronicsConstants;

@Entity
@Table(name = "order_items")
@Configurable
public class OrderItem {

	@PersistenceContext
	transient EntityManager entityManager;

	@Id
	@TableGenerator(name = "orderItemGenerator", pkColumnValue = "ORDER_ITEMS", table = OptitronicsConstants.COUNTER_TABLE_NAME, pkColumnName = OptitronicsConstants.COUNTER_PK_COLUMN_NAME, valueColumnName = OptitronicsConstants.COUNTER_VALUE_COLUMN_NAME, allocationSize = OptitronicsConstants.COUNTER_ALLOCATION_SIZE)
	@GeneratedValue(strategy = GenerationType.TABLE, generator = "orderItemGenerator")
	@Column(name = "ID")
	private Integer id;

	@ManyToOne
	@JoinColumn(name = "RESELLER_ORDER_ID", referencedColumnName = "ID")
	private ResellerOrder resellerOrder;

	@ManyToOne
	@JoinColumn(name = "PRODUCT_ID", referencedColumnName = "ID")
	private Product product;

	@Version
	@Column(name = "VERSION")
	private Integer version;

	@Column(name = "QUANTITY")
	private Integer quantity;

	@Column(name = "PRICE_TYPE")
	private Integer priceType;

	@Column(name = "DISCOUNT")
	private BigDecimal discount;

	@Column(name = "AMOUNT_WITHOUT_TAX")
	private BigDecimal amountWithoutTax;

	@Column(name = "AMOUNT_WITH_TAX")
	private BigDecimal amountWithTax;

	@Column(name = "UNIT_PRICE_WITHOUT_TAX")
	private BigDecimal unitPrice;

	@Column(name = "BUYER_NAME")
	@NotNull
	private String buyerName;

	@Column(name = "BUYER_EMAIL")
	@NotNull
	private String buyerEmail;

	@Column(name = "BUYER_CITY")
	@NotNull
	private String buyerCity;

	@Column(name = "BUYER_ADDRESS")
	@NotNull
	private String buyerAddress;

	@Column(name = "ORDINAL")
	private Integer ordinal;

	@Column(name = "BUYER_CONTACT_PERSON")
	private String buyerContactPerson;

	@Column(name = "BUYER_PHONE")
	private String buyerPhone;

	@Column(name = "DOCUMENT_NAME")
	private String documentName;

	@ManyToOne
	@JoinColumn(name = "BUYER_ID", referencedColumnName = "ID")
	private Client buyer;

	@Transactional
	public void persist() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		this.entityManager.persist(this);
	}

	@Transactional
	public void flush() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		this.entityManager.flush();
	}

	public static final EntityManager entityManager() {
		EntityManager em = new OrderItem().entityManager;
		if (em == null)
			throw new IllegalStateException(
					"Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
		return em;
	}

	public static OrderItem findOrderItem(Integer id) {
		if (id == null)
			return null;
		return entityManager().find(OrderItem.class, id);
	}

	public static List<OrderItem> findOrderItems(Integer orderId) {
		TypedQuery<OrderItem> query = entityManager().createQuery(
				"select o from OrderItem o WHERE o.resellerOrder.id = :orderId ORDER BY o.ordinal", OrderItem.class);
		return query.setParameter("orderId", orderId).getResultList();
	}

	@SuppressWarnings("unchecked")
	public static List<OrderItemDisplayForm> findClientOrderItems(Integer buyerId) {

		String queryString = "select new com.optitronics.ui.OrderItemDisplayForm(o) from OrderItem o "
				+ "WHERE o.buyer.id = :buyerId ORDER BY o.resellerOrder.orderDate";

		Query query = entityManager().createQuery(queryString);
		return query.setParameter("buyerId", buyerId).getResultList();
	}

	public Date getOrderDate() {
		return this.getResellerOrder().getOrderDate();
	}

	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public ResellerOrder getResellerOrder() {
		return this.resellerOrder;
	}

	public void setResellerOrder(ResellerOrder resellerOrder) {
		this.resellerOrder = resellerOrder;
	}

	public Product getProduct() {
		return this.product;
	}

	public String getProductName() {
		return this.product.getName();
	}

	public void setProduct(Product product) {
		this.product = product;
	}

	public Integer getVersion() {
		return this.version;
	}

	public void setVersion(Integer version) {
		this.version = version;
	}

	public Integer getPriceType() {
		return this.priceType;
	}

	public void setPriceType(Integer priceType) {
		this.priceType = priceType;
	}

	public String getBuyerName() {
		return this.buyerName;
	}

	public void setBuyerName(String buyerName) {
		this.buyerName = buyerName;
	}

	public String getBuyerEmail() {
		return this.buyerEmail;
	}

	public void setBuyerEmail(String buyerEmail) {
		this.buyerEmail = buyerEmail;
	}

	public String getBuyerCity() {
		return this.buyerCity;
	}

	public void setBuyerCity(String buyerCity) {
		this.buyerCity = buyerCity;
	}

	public String getBuyerAddress() {
		return this.buyerAddress;
	}

	public void setBuyerAddress(String buyerAddress) {
		this.buyerAddress = buyerAddress;
	}

	public String getBuyerContactPerson() {
		return this.buyerContactPerson;
	}

	public void setBuyerContactPerson(String buyerContactPerson) {
		this.buyerContactPerson = buyerContactPerson;
	}

	public String getBuyerPhone() {
		return this.buyerPhone;
	}

	public void setBuyerPhone(String buyerPhone) {
		this.buyerPhone = buyerPhone;
	}

	public Integer getQuantity() {
		return quantity;
	}

	public void setQuantity(Integer quantity) {
		this.quantity = quantity;
	}

	public EntityManager getEntityManager() {
		return entityManager;
	}

	public void setEntityManager(EntityManager entityManager) {
		this.entityManager = entityManager;
	}

	public BigDecimal getAmountWithTax() {
		return amountWithTax;
	}

	public void setAmountWithTax(BigDecimal amountWithTax) {
		this.amountWithTax = amountWithTax;
	}

	public BigDecimal getAmountWithoutTax() {
		return amountWithoutTax;
	}

	public void setAmountWithoutTax(BigDecimal amountWithoutTax) {
		this.amountWithoutTax = amountWithoutTax;
	}

	public Integer getOrdinal() {
		return ordinal;
	}

	public void setOrdinal(Integer ordinal) {
		this.ordinal = ordinal;
	}

	public Client getBuyer() {
		return buyer;
	}

	public void setBuyer(Client buyer) {
		this.buyer = buyer;
	}

	public BigDecimal getDiscount() {
		return discount;
	}

	public void setDiscount(BigDecimal discount) {
		this.discount = discount;
	}

	public BigDecimal getUnitPrice() {
		return unitPrice;
	}

	public void setUnitPrice(BigDecimal unitPrice) {
		this.unitPrice = unitPrice;
	}

	public BigDecimal getUnitPriceWithDiscount() {

		BigDecimal discountPerc = this.discount == null ? BigDecimal.ZERO : this.discount;
		BigDecimal multiplicand = BigDecimal.valueOf(100.00).subtract(discountPerc);
		multiplicand = multiplicand.divide(BigDecimal.valueOf(100.00), 2, BigDecimal.ROUND_HALF_UP);

		return this.unitPrice.multiply(multiplicand);
	}

	public String getDocumentName() {
		return documentName;
	}

	public void setDocumentName(String documentName) {
		this.documentName = documentName;
	}
}
